// Learn TypeScript:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/typescript.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html

import Hero from "../hero";
import Camera from "../camera";
import Rank from "./rank";
import Timer from "./timer";
import {GAME_SECOND, MAP_CONFIG} from "../config/config";
import ResultBoard from "../result/resultBoard";
import {GameMode, GameVar, GlobalObject} from "./GameVar";
import Killboard from "./killboard";
import {HeroFactory, heroFactory} from "../hero/HeroFactory";
import {ballFactory, BallFactory} from "./ballFactory";
import EnergyProgress from "./energyProgress";
import {model} from "../web/model/Model";
import {globalConfig} from "../config/globalConfig";
import {utils} from "../utils/utils";
import ReviveBoard from "./reviveBoard";
import {wxUtils} from "../wx/wxUtils";
import UpdateController from "../frame/UpdateController";
import Controls from "../controls";

const {ccclass, property} = cc._decorator;

@ccclass
export default class GameBoard extends cc.Component {

  gridWidth = 64;

  @property(cc.Prefab)
  pointPrefab: cc.Prefab = null;

  @property(cc.Node)
  pointsBoard: cc.Node = null;

  @property(cc.Prefab)
  heroPrefab: cc.Prefab = null;

  @property(cc.Node)
  heroesBoard: cc.Node = null;

  @property(cc.Node)
  hero: cc.Node = null;

  @property(cc.Node)
  rankNode: cc.Node = null

  @property(cc.Node)
  timer: cc.Node = null

  @property(cc.Node)
  result: cc.Node = null

  @property(cc.Node)
  beKilledBoard: cc.Node = null;

  @property(cc.Node)
  private progressBar: cc.Node = null;

  @property(cc.Node)
  private killBoard: cc.Node = null;

  @property(cc.Prefab)
  guidePrefab: cc.Prefab = null;

  @property(cc.Prefab)
  revivePrefab: cc.Prefab = null;

  @property(UpdateController)
  updateController: UpdateController = null;

  @property(Controls)
  controls: Controls = null;

  resultScript: ResultBoard

  camera: Camera = null;

  rank: Rank;

  heroScript: Hero;

  private minPoint = MAP_CONFIG.bubblecount;
  private aiHeroes = []
  private heroFactory: HeroFactory = null;
  private ballFactory: BallFactory = null;

  onLoad() {

    this.camera = this.node.getComponent(Camera)
    this.rank = this.rankNode.getComponent(Rank)

    this.initPoints();
    this.initMyHero();

    this.progressBar.getComponent(EnergyProgress).setFocus(this.heroScript)
    this.resultScript = this.result.getComponent(ResultBoard)
    wxUtils.postMessage({cmd: 'enterGame'})
  }

  initMyHero() {
    this.heroFactory = heroFactory;
    this.heroFactory.init(this.heroPrefab)
    this.hero = this.heroFactory.createMyHero(this)
    const heroScript = this.hero.getComponent(Hero)
    this.killBoard.getComponent(Killboard).hero = this.hero;
    this.heroScript = heroScript;
    this.controls.hero = this.hero;
    this.camera.focus = this.hero;
    this.rank.setHero(heroScript)
  }

  start() {
    this.showGuide();
    this.restart();
    if (GameVar.mode === GameMode.LIMITED) {
      this.timer.on('timerEnd', this.onTimerEnd, this)
      this.timer.active = true;
    } else {
      this.timer.active = false;
    }
    GlobalObject.voiceSource.playBattleBgm();
  }

  private _nodePool: cc.NodePool;

  private initPoints() {
    this.ballFactory = ballFactory;
    this.ballFactory.init(this.pointPrefab, this)
  }

  private createHeroes() {
    this.createAiHeroes()
  }

  private createAiHeroes() {
    utils.addGameCount()
    const difficultyConfig = this.getDifficultyConfig()
    difficultyConfig.aiCount.forEach((value, index) => {
      for (let i = 0; i < value; i++) {
        const aiConfig = globalConfig.ai[index]
        const hero = this.heroFactory.createAI(this, aiConfig)
        this.aiHeroes.push(hero.node);
        this.rank.addUser(hero.user);
      }
    })
  }

  private getDifficultyConfig() {
    // const myGameCount = utils.getGameCount()
    // for (let i = globalConfig.aidifficulty.length - 1; i >= 0; i--) {
    //   const difficultyConfig = globalConfig.aidifficulty[i]
    //   if (myGameCount >= difficultyConfig.gameCount) {
    //     return difficultyConfig
    //   }
    // }
    return globalConfig.aidifficulty[0]
  }

  get nodePool(): cc.NodePool {
    return this._nodePool;
  }

  updateFixedFrame(dt) {
    if (this.pointsBoard.children.length < this.minPoint) {
      this.ballFactory.create();
    }
  }

  private startTime: number = 0;
  private endTime: number = 0;

  restart() {
    this.startTime = Date.now()
    GameVar.gameEnd = false;
    //重置排行榜
    this.rank.node.active = true;
    this.rank.reset();
    //重置我的角色
    this.hero.active = true;
    this.heroScript.reborn();
    this.heroScript.score = 0;
    this.heroScript.kill = 0;
    this.heroScript.beKill = 0;
    this.heroScript.continousKill = 0;
    this.heroScript.energy = 0;
    this.rank.addUser(this.heroScript.user)
    //重置ai角色
    this.resetHero();
    this.createHeroes();
    //重置左上角
    this.killBoard.getComponent(Killboard).reset()
    //重置摄像头
    this.camera.focus = this.hero;
    //时间重置
    this.timer.getComponent(Timer).startTimer(GAME_SECOND)
    //复活次数
    this.rebornCount = 0;
  }

  /**
   * 时间到，游戏结束
   */
  onTimerEnd() {
    this.endTime = Date.now()
    this.resultScript.show(this.heroScript, Math.floor((this.endTime - this.startTime) / 1000))
    this.beKilledBoard.active = false;
    this.hero.active = false;
    this.rank.node.active = false;
    this.rank.reset();
    this.changeCameraFocus();
    GameVar.gameEnd = true;
  }

  private rebornCount = 0;

  /**
   * 无限积分结束
   */
  onInfiGameEnd() {
    // const reviveSwitch = model.user.switch;
    const reviveSwitch = false;
    if (reviveSwitch && this.rebornCount < 5) {
      const reviveBoard = this.getReviveBoard();
      reviveBoard.parent = cc.director.getScene()
      wxUtils.showReviveAd();
      reviveBoard.getComponent(ReviveBoard).setScore(this.heroScript.score, this.rebornCount)
    } else if (!reviveSwitch && this.rebornCount < 5) {
      const reviveBoard = this.getReviveBoard();
      reviveBoard.parent = cc.director.getScene()
      wxUtils.showReviveAd();
      reviveBoard.getComponent(ReviveBoard).setScore(this.heroScript.score, 5)
    } else {
      this.onTimerEnd();
    }
    this.rebornCount++
  }

  resetHero() {
    while (this.aiHeroes.length > 0) {
      const hero: cc.Node = this.aiHeroes.shift();
      this.heroFactory.recycleHero(hero);
    }
  }

  changeCameraFocus() {
    const players = this.node.getChildByName('players').children
    this.camera.focus = players[Math.floor(players.length * Math.random())]
  }

  private showGuide() {
    const notNewbie = cc.sys.localStorage.getItem('notNewbie')
    if (notNewbie == null || notNewbie == "") {
      cc.director.pause();
      cc.instantiate(this.guidePrefab).parent = cc.director.getScene();
      cc.sys.localStorage.setItem('notNewbie', '1')
    }
  }

  private reviveNode: cc.Node = null;

  getReviveBoard() {
    if (!this.reviveNode) {
      this.reviveNode = cc.instantiate(this.revivePrefab)
      this.reviveNode.on('pass', () => {
        this.onTimerEnd()
      })
    }
    return this.reviveNode;
  }
}
